package com.chun.api;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.context.ApplicationContext;

public class ApiStore {

	private ApplicationContext applicationContext ;
	private Map<String, ApiRunnable> apiMap = new HashMap<String, ApiRunnable>();
	
	public ApiStore(ApplicationContext applicationContext){
		this.applicationContext = applicationContext;
	}
	
	public void loadApiFromSpringBeans(){
		String[] names = applicationContext.getBeanDefinitionNames();
		Class<?> type;
		for(String name:names){
			type = applicationContext.getType(name);
			for(Method m:type.getDeclaredMethods()){
				APIMapping apiMapping = m.getAnnotation(APIMapping.class);
				if (apiMapping != null ) {
					addApiItem(apiMapping,name,m);
				}
			}
			
		}
		
		
		
	}

	public ApiRunnable findApiRunnable(String apiName) {
		return apiMap.get(apiName);
		
	}
	private void addApiItem(APIMapping apiMapping, String beanName, Method method) {
		 ApiRunnable apiRun = new ApiRunnable();
		 apiRun.apiName = apiMapping.value();
		 apiRun.targetMethond = method;
		 apiRun.targetName = beanName;
		 
		 apiMap.put(apiMapping.value(), apiRun);
	}
	public ApiRunnable findApiRunnable(String apiName,String version){
		return  apiMap.get(apiName+"_"+version);
	}
	public List<ApiRunnable> findApiRunnables(String apiName){
		if (apiName == null) {
			throw new IllegalArgumentException("api name must not null!");
		}
		List<ApiRunnable> apiRunnables = new ArrayList<ApiRunnable>(20);
		for(ApiRunnable apiRunnable: apiMap.values()){
			if (apiRunnable.apiName.equals(apiName)) {
				apiRunnables.add(apiRunnable);
			}
		}
		return apiRunnables;
	}
	
	public class ApiRunnable {
		public String apiName;
		public Method targetMethond;
		public String targetName;
		public Object target;
		public Object run(Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
			if (target == null) {
				target = applicationContext.getBean(targetName);
			}
			return targetMethond.invoke(target, args);
		}
		
		public Class<?>[]  getParamTypes() {
			return targetMethond.getParameterTypes();
		}
		public String getApiName(){
			return apiName;
		}
		public String getTargetName(){
			return targetName;
		}
		public Object getTarget(){
			return target;
		}
	}
}
